import es
import random
import playerlib
import weaponlib

import wcs

raceName = "Orcish Horde"
race     = wcs.races[raceName]

""" Load the strings into the variable text """
text     = race.loadStrings()

""" ############################### """
""" ### Begin the configuration ### """
""" ############################### """

config   = race.config()

config.text("********************")
config.text("Critical Strike")
config.text("  This skill gives a chance of dealing additional damage")
config.text("  to others.")
config.text("********************")
config.text("")
critStrikeMaxLevel      = config.cvar("critStrikeMaxLevel",      6, "The maximum level for the Critical Strike Skill")
critStrikeLevelInterval = config.cvar("critStrikeLevelInterval", 2, "The intervals between the abilities to upgrade their Critical Strike skill")
critStrikeDamage        = config.cvar("critStrikeDamage",        6, "This is the amount of additional damage gave multiplied by their level")

config.text("")
config.text("********************")
config.text("Critical Grenade")
config.text("  This skill deals additional damage with grenades")
config.text("********************")
config.text("")
critNadeMaxLevel        = config.cvar("critNadeMaxLevel",      8, "The maximum level for the Critical Grenade skill")
critNadeLevelInterval   = config.cvar("critNadeLevelInterval", 4, "The intervals between the abilities to upgrade their Critical Grenade skill")
critNadeDamage          = config.cvar("critNadeDamage",       10, "The additional damage a critical grenade will damage multipplied by their level.") 

config.text("")
config.text("********************")
config.text("Reincarnation")
config.text("  This skill gives a chance of respawning after death")
config.text("********************")
config.text("")
reinMaxLevel           = config.cvar("reinMaxLevel",      5, "The maximum level for the Reincarnation skill")
reinLevelInterval      = config.cvar("reinLevelInterval", 5, "The intervals between the abilities to upgrade their Reincarnation skill")
reinPercent            = config.cvar("reinPercent",      10, "The chance in percent that a player will respawn after death, multiplied by their level")

config.text("")
config.text("********************")
config.text("Chain Lightning")
config.text("  This ultimate allows you to power up yourself to") 
config.text("  run in and shock all near by enemies.") 
config.text("  The maximum a player can charge to is a damage counter")
config.text("  of power 10.")
config.text("********************")
config.text("")
chainMinLevel         = config.cvar("chainMinLevel",        8,  "The level required before this ultimate can be bought")
chainMaxLevel         = config.cvar("chainMaxLevel",        8,  "The maximum level for the Suicide Bomber skill")
chainLevelInterval    = config.cvar("chainLevelInterval",   4,  "The interval between the skill upgrades")
chainCoolDown         = config.cvar("chainCoolDown",        18, "The amount of seconds after a player has used their ultimate that they cannot use it again")
chainDamage           = config.cvar("chainDamage",          2,  "The amount of damage done multiplied by their Chain level multiplied further by the damage counter (keep this betwee 1 and 4)")
chainDistance         = config.cvar("chainDistance",        50, "The distance (in game units) multiplied by the damage counter that people will be effected. (40 game units = 1m)")

config.load(True)

""" ##################### """
""" ### END OF CONFIG ### """
""" ##################### """

race.registerSkill("Critical Strike", int(critStrikeMaxLevel), int(critStrikeLevelInterval), "Have a chance of hitting a critical hit")
race.registerSkill("Critical Grenade", int(critNadeMaxLevel), int(critNadeLevelInterval), "You grenades will do additional damage")
race.registerSkill("Reincarnation", int(reinMaxLevel), int(reinLevelInterval), "Enables a random chance of respawning when you die")        
race.registerUltimate("Chain Lightning", int(chainMinLevel), int(chainMaxLevel), int(chainLevelInterval), "Hold down the ultimate key to release a bolt of lightning")

def player_hurt(event_var):
    """
    Executed whenever a player is hurt. We"ll need to see if the player was
    first hurt by a grenade; if so, then apply the additional cirtical grenade
    damage. Otherwise, we"ll need to run a dict throw to see if the user has
    a chance of doing a critical string.
    """
    attacker = event_var["attacker"]
    if attacker and int(attacker):
        userid = event_var["userid"]
        userteam = event_var["es_userteam"]
        attackerteam = event_var["es_attackerteam"]
        wcsUserid = wcs.players[userid]
        wcsAttacker = wcs.players[attacker]
        
        if userteam != attackerteam and attacker:
            """ Players are on opposite teams, so do the critical strikes """
            critStrike = wcsAttacker[raceName]["Critical Strike"]
            critNade   = wcsAttacker[raceName]["Critical Grenade"]
            weapon = weaponlib.getWeapon(event_var["weapon"])
            
            if critNade and weapon.name in weaponlib.getWeaponNameList("#grenade"):
                """
                If the weapon was a grenade and the players critical nade level
                is at least level one, then apply the critical damage
                """
                damage = critNade * int(critNadeDamage)
                wcsUserid.damage(damage, 32, attacker)
                tokens = {}
                tokens["victim"]   = event_var["es_username"]
                tokens["attacker"] = event_var["es_attackername"]
                tokens["damage"]   = damage
                es.tell(userid,   "#multi", text("critical nade victim",   tokens, playerlib.getPlayer(userid).get("lang")))
                es.tell(attacker, "#multi", text("critical nade attacker", tokens, playerlib.getPlayer(attacker).get("lang")))
                
            elif critStrike:
                """ 
                If the weapon was not an hegrenade or the player doesn"t have a 
                level in critNade, run this method.
                """
                chance = random.randint(1, 20)
                if chance <= critStrike:
                    damage = critStrike * int(critStrikeDamage)
                    wcsUserid.damage(damage, 32, attacker)
                    tokens = {}
                    tokens["victim"]   = event_var["es_username"]
                    tokens["attacker"] = event_var["es_attackername"]
                    tokens["damage"]   = damage
                    es.tell(userid,   "#multi", text("critical strike victim",   tokens, playerlib.getPlayer(userid).get("lang")))
                    es.tell(attacker, "#multi", text("critical strike attacker", tokens, playerlib.getPlayer(attacker).get("lang")))
                    
def player_death(event_var):
    """
    Executed when a player dies. Ensure that we see if the player has the
    reincarnation skill. If they do, and the chance of respawning has 
    executed, then make sure the player is respawned in 1 second.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    reincarnation = player[raceName]["Reincarnation"]
    if reincarnation:
        rand = random.randint(1, 100) 
        if rand <= reincarnation * int(reinPercent): 
            player.delayed(1, spawnUserid, userid)

def player_ultimate_on(event_var):
    """
    Executed when an ultimate key is pressed down. Begin the lighting charge
    timer if they have an ultimate level.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    chain  = player[raceName]["Chain Lightning"]
    if chain:
        player["lightPower"] = 0
        addPower(userid)

def player_ultimate_off(event_var):
    """
    Executed when the ultimate key is let go. Stop the lightning charge timer
    and execute the 'shock' effect.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    chain = player[raceName]["Chain Lightning"]
    player.cancelDelayed("lightning")
    if chain:
        damage = player["lightPower"]
        if damage:
            player.setCoolDown("Chain Lightning", int(chainCoolDown))
            if damage <= 5:
                sound = random.choice(["spark%s" % x for x in xrange(4, 7)])
            else:
                sound = random.choice(["zap%s" % x for x in xrange(1, 4)])
            sound = "ambient/energy/%s.wav" % sound
            es.emitsound("player", userid, sound, 0.5, 0.5)
            player.near(damage * int(chainDistance), damagePlayer, ("#t" if event_var["es_userteam"] == "3" else "#ct"))
        del command["lightPower"]
        
def addPower(userid):
    """
    Executed when we wish to add a power value to the current player. Ensure
    that we increment the current power level by 1 until we reach a maximum
    of 10.
    
    @param int userid The ID of the user we wish to increment the light power
    """
    player = wcs.players[userid]
    if "lightPower" not in player:
        player["lightPower"] = 0
    power = player["lightPower"]
    if power < 10:
        player["lightPower"] += 1
        player.hudHint("%s\n%s" % (text("power", lang=playerlib.getPlayer(userid).get("lang")), "|" * (power + 1)))
        es.emitsound("player", userid, wcs.BLIP, 0.5, 0.5)
    else:
        player.hudHint("%s\n%s" % (text("power", lang=playerlib.getPlayer(userid).get("lang")), text("maxed", lang=playerlib.getPlayer(userid).get("lang"))))
    player.delayedName(0.5, "lightning", addPower, userid)
        
def spawnUserid(userid):
    """
    Executed when we want to spawn a player. The reason we have a custom
    function is down to the fact we want to check the living player count for
    the players team, if there are any survivors (i.e the round is still not
    over) then respawn him.
    
    @param int userid The ID of the user we wish to spawn.
    """
    if es.getlivingplayercount(es.getplayerteam(userid)):
        """ If we are here then there are team mates alive. """
        wcs.players[userid].spawn()
        es.tell(userid, "#multi", text("reincarnation", lang=playerlib.getPlayer(userid).get("lang")))

def damagePlayer(userid, attacker):
    """
    Executed for each player within the radius of the chain lightning damage.
    Assume that we want to damage the victim by a given calculated amount.
    
    @param int userid The ID of the user we wish to damage
    @param int attacker The ID of the attacker who executed the chain lightning
    """
    wcsAttacker = wcs.players[attacker]
    damage = wcsAttacker["lightPower"] * int(chainDamage) * wcsAttacker[raceName]["Chain Lightning"]
    wcs.players[userid].damage(damage, 32, attacker)
    tokens = {}
    tokens["victim"]   = es.getplayername(userid)
    tokens["attacker"] = es.getplayername(attacker)
    tokens["damage"]   = damage
    es.tell(attacker, "#multi", text("chain lightning attacker", tokens, playerlib.getPlayer(attacker).get("lang")))
    es.tell(userid, "#multi", text("chain lightning victim", tokens, playerlib.getPlayer(userid).get("lang")))
